package online

import (
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleCallEndAck(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleCallEndAck")

	var resData common.ResMsgData
	if err := mapstructure.Decode(msg.Data, &resData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("invalid message data format")
		return nil
	}

	var ackData common.CallEndAckData
	if err := mapstructure.Decode(resData, &ackData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to decode call end ack data")
		return nil
	}

	if ackData.CallId == "" {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).Error("callId is empty in call end ack")
		return nil
	}

	call, exists := s.callMgr.GetCall(ackData.CallId)
	if !exists {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).
			Errorf("call does not exist: %s", ackData.CallId)
		return nil
	}

	if call.CallState != Terminating {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).
			Errorf("call state is not Terminating, current state: %d", call.CallState)
		return nil
	}

	if err := s.callMgr.updateCallState(ackData.CallId, Terminated); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to update call state to Terminated")
		return &common.AppError{
			ErrCode: 500, ErrMsg: "failed to update call state to Terminated: " + err.Error(),
		}
	}

	s.callMgr.RemoveCall(ackData.CallId)

	responseMsg := common.Message{
		Cmd: common.CALL_END_RES,
		Rid: msg.Rid,
		Data: common.ResMsgData{
			Code: 0,
			Msg:  "Call ended successfully",
			Data: common.CallEndResData(ackData),
		},
	}
	if err := s.dispatcher.Dispatch(responseMsg, s.serviceInfo, from, connId); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to send call end response")
	}

	return nil
}
